home *** CD-ROM | disk | FTP | other *** search
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i174: ED3 1.1 - a primitive 3D editor for use with NU3, Part03/06
- Reply-To: rodent@netcom.com (Ben Discoe)
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga.v91i174@ab20.larc.nasa.gov>
- References: <comp.sources.amiga.v91i172@ab20.larc.nasa.gov>
- Date: 07 Nov 91 15:54:25 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: rodent@netcom.com (Ben Discoe)
- Posting-number: Volume 91, Issue 174
- Archive-name: utilities/ed3-1.1/part03
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 6)."
- # Contents: edio.c freq.c
- # Wrapped by tadguy@ab20 on Thu Nov 7 10:53:52 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'edio.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'edio.c'\"
- else
- echo shar: Extracting \"'edio.c'\" \(24785 characters\)
- sed "s/^X//" >'edio.c' <<'END_OF_FILE'
- X/*
- X These are functions of ed3 that do keyboard, mouse and file IO.
- X
- X10-22-91 chg YZ to ZY
- X10-21-91 fix to allow saving defaults!
- X10-20-91 fix to refresh after loading!
- X10-13-91 add tell_user_overflow() and tell_user_changes(), get_undo_bufsize()
- X add load_defaults() and save_defaults()
- X09-09-91 made handle_key() portable
- X09-04-91 chg load_data to call add_point, add_face
- X09-06-91 adapted to use coord instead of short
- X*/
- X
- X#include "sysnogr.h"
- X
- X/* Menu numbers */
- X#define ME_PROJECT 0
- X#define ME_EDIT 1
- X#define ME_POLYHEDRA 2
- X#define ME_SPECIAL 3
- X#define ME_OPTIONS 4
- X
- X/* Menu items numbers */
- X#define MI_LOAD 0
- X#define MI_SAVE 1
- X#define MI_CLEAR 2
- X/* --- 3 */
- X#define MI_SAVE_DEF 4 /* save defaults */
- X#define MI_ABOUT 5
- X/* --- 6 */
- X#define MI_QUIT 7
- X
- X#define MI_CUT 0
- X#define MI_COPY 1
- X#define MI_PASTE 2
- X#define MI_DUPLICATE 3
- X#define MI_ERASE 4
- X#define MI_SELECTALL 6
- X#define MI_SELECTCON 7
- X#define MI_DESELECTALL 8
- X#define MI_POINTSONLY 10
- X#define MI_FACESONLY 11
- X#define MI_EXCLUSIVE 12
- X
- X#define MI_TETRA 0
- X#define MI_OCTA 1
- X#define MI_CUBE 2
- X#define MI_ICOSA 3
- X#define MI_DODEC 4
- X#define MI_DODEC_RHOMB 5
- X#define MI_CUBOCTA 6
- X/* --- 7 */
- X#define MI_GLOBE 8
- X#define MI_SURF_REV 9
- X
- X#define MI_RESET_ZOOM 0
- X#define MI_FREQUENCY 1
- X#define MI_CONNECT 2
- X#define MI_DUAL 3
- X#define MI_UNFOLD 4
- X#define MI_NORMALIZE 5
- X#define MI_STELLATE 6
- X#define MI_ORIGIN 7
- X#define MI_SETCLOCK 8
- X
- Xchar *errstring[ERRORS] =
- X{
- X "Everything is Okay",
- X "There was nothing it that file",
- X "Can't open file",
- X "That's not the kind of file ED3 can read",
- X "Not enough memory",
- X "Not enough memory for points",
- X "Not enough memory for faces",
- X "Not enough memory for polygons",
- X "Bad face: face refers to non-existent point"
- X};
- X
- X
- Xvoid handle_gadget(id)
- Xint id;
- X{
- X switch (id)
- X {
- X case GID_ADD: mode = M_ADDP; break;
- X case GID_DELETE: mode = M_DELP; break;
- X case GID_SELECTOR: mode = M_SELE; break;
- X case GID_MOVE: mode = M_MOVP; break;
- X case GID_FACE: mode = M_FACE; break; /* new face */
- X case GID_POLY: mode = M_POLY; break; /* new polygon */
- X case GID_MORE: break;
- X case GID_DEFACE: mode = M_DEFA; deselect_all(); break;
- X case GID_DEPOLY: mode = M_DEPO; deselect_all(); break;
- X case GID_MORE2: break;
- X case GID_ROTATE: mode = M_ROTA; break;
- X case GID_ROTP: break;
- X case GID_ZOOM: mode = M_ZOOM; break;
- X case GID_DIST:
- X mode = M_DIST;
- X if (!flags.display_dtool)
- X {
- X flags.display_dtool = 1;
- X toggle_menuitem(ME_OPTIONS, MI_DISTANCETOOL);
- X draw_distance_tool();
- X }
- X break;
- X case GID_GLUE: mode = M_GLUE; break;
- X case GID_UNDO: undo(); break;
- X case GID_REDO: redo(); break;
- X case GID_XY: dmode = DM_XY; gz = 0; break;
- X case GID_XZ: dmode = DM_XZ; gy = 0; break;
- X case GID_ZY: dmode = DM_ZY; gx = 0; break;
- X case GID_3D: break;
- X case GID_color1: colors.newface = 1; break;
- X case GID_color2: colors.newface = 2; break;
- X case GID_color3: colors.newface = 3; break;
- X }
- X switch (id)
- X {
- X case GID_XY:
- X case GID_XZ:
- X case GID_ZY:
- X convert_points();
- X refresh_all();
- X }
- X draw_bars();
- X}
- X
- X
- Xvoid mouse_down(buttons) /* what to do when a mouse button is pressed */
- Xchar buttons; /* 0 = first, 1 = second, 2 = double click with first */
- X{
- X index nearest; /* closest point to the cursor */
- X
- X convert_to_xyz(mx, my);
- X
- X switch(mode) /* many mode need to operate on the selected point */
- X {
- X case M_DELP:
- X case M_SELE:
- X case M_DEFA:
- X case M_DEPO:
- X case M_FACE:
- X case M_POLY:
- X case M_MOVP:
- X case M_MORE:
- X case M_KMORE:
- X case M_DIST:
- X case M_GLUE:
- X if (buttons & 1) /* second button */
- X nearest = find_nearest_in_space(gx, gy, gz, -1);
- X else
- X nearest = find_nearest_on_screen(mx, my, -1);
- X }
- X switch(mode)
- X {
- X case M_ADDP:
- X begin_operation();
- X draw_point(add_point(gx, gy, gz), colors.point);
- X end_operation();
- X break;
- X case M_DELP:
- X begin_operation();
- X del_point(nearest, 0, 0);
- X end_operation();
- X break;
- X case M_SELE:
- X toggle_select(buttons, nearest);
- X break;
- X case M_MOVP:
- X start_moving_point(buttons, nearest);
- X break;
- X case M_FACE: start_face(nearest); break;
- X case M_POLY: start_poly(nearest); break;
- X case M_MORE: add_segment(nearest); break;
- X
- X case M_DEFA: start_to_kill_face(nearest); break;
- X case M_DEPO: start_to_kill_poly(nearest); break;
- X case M_KMORE: kill_segment(nearest); break;
- X
- X case M_ROTA: set_rot_axis(gx, gy, gz); break;
- X case M_ROTP: rotate(); break;
- X case M_ZOOM: zoom(buttons); break;
- X case M_DIST: distance_tool(buttons, nearest); break;
- X case M_GLUE: glue(nearest); break;
- X }
- X show_counts();
- X}
- X
- X
- Xvoid mouse_up() /* what to do when the first button goes up */
- X{
- X if (flags.moving_points) finish_move();
- X if (flags.drag_dtool)
- X {
- X#if 0
- X draw_distance_tool();
- X#endif
- X flags.drag_dtool = 0;
- X }
- X show_counts();
- X}
- X
- X
- Xvoid update_movement(newx, newy)
- Xcoord newx, newy;
- X{
- X mx = newx;
- X my = newy;
- X
- X if (flags.in_edit_area)
- X {
- X /* have we moved out? */
- X if (mx <= edit_minx || my <= edit_miny)
- X {
- X flags.in_edit_area = 0;
- X enable_menus(TRUE);
- X }
- X }
- X else
- X {
- X /* have we moved in? */
- X if (mx > edit_minx && my > edit_miny)
- X {
- X flags.in_edit_area = 1;
- X enable_menus(FALSE);
- X }
- X }
- X
- X if (!flags.in_edit_area) return;
- X
- X /* erase stuff */
- X if (flags.crosshair) draw_hair(); /* Erase/Redraw crosshair */
- X if (flags.drag_dtool)
- X draw_distance_tool(); /* Erase/Redraw distance tool */
- X if (flags.moving_points) /* If we are dragging some points */
- X toggle_dragged_points(); /* then erase them */
- X
- X /* allow the pointer to move */
- X convert_to_xyz(mx, my);
- X if (flags.show_coords) draw_coords(0);
- X
- X /* redraw stuff */
- X if (flags.moving_points) /* If we are dragging some points */
- X toggle_dragged_points(); /* then redraw them */
- X if (flags.drag_dtool)
- X {
- X dtool_end[flags.which_end].x = gx;
- X dtool_end[flags.which_end].y = gy;
- X dtool_end[flags.which_end].z = gz;
- X draw_distance_tool(); /* Erase/Redraw distance tool */
- X }
- X if (flags.crosshair) draw_hair(); /* Erase/Redraw crosshair */
- X if (mode == M_ROTP)
- X {
- X draw_rot(); /* Erase angle */
- X convert_to_xy(axis.x, axis.y, axis.z);
- X rot_angle = atan2((double)(py-my), (double)(mx-px));
- X draw_rot(); /* Redraw angle */
- X }
- X}
- X
- X
- Xvoid handle_key(key)
- Xshort key;
- X{
- X /* first, keys that work in all modes */
- X
- X switch(key)
- X {
- X case 27: /* Esc */
- X if (!selected)
- X select_all();
- X else
- X deselect_all();
- X break;
- X case 'c':
- X flags.crosshair ^= 1;
- X toggle_menuitem(ME_OPTIONS, MI_CROSSHAIR);
- X draw_hair();
- X break;
- X case 'd':
- X toggle_menuitem(ME_OPTIONS, MI_DISTANCETOOL);
- X toggle_dtool();
- X break;
- X case 'm':
- X mode = M_MOVP;
- X deselect_all();
- X break;
- X case 'u': undo(); break;
- X case 'r': redo(); break;
- X case 8:
- X del_selected();
- X show_counts(); /* it's likely we've changed something */
- X break;
- X case 'x': flags.debug ^= 1; break;
- X case '8':
- X if (dmode == DM_XY) gz++;
- X if (dmode == DM_XZ) gy++;
- X if (dmode == DM_ZY) gx++;
- X if (flags.show_coords) draw_coords(0); break;
- X case '2':
- X if (dmode == DM_XY) gz--;
- X if (dmode == DM_XZ) gy--;
- X if (dmode == DM_ZY) gx--;
- X if (flags.show_coords) draw_coords(0); break;
- X case 'a': zoom(1); break;
- X case 'z': zoom(0); break;
- X case ' ':
- X convert_points();
- X refresh_all();
- X break;
- X }
- X}
- X
- X
- Xvoid handle_menu(menunum, itemnum, flags)
- Xint menunum, itemnum, flags;
- X{
- X switch (menunum)
- X {
- X case ME_PROJECT:
- X handle_project(itemnum); break;
- X case ME_EDIT:
- X handle_edit(itemnum, flags); break;
- X case ME_POLYHEDRA:
- X handle_polyhedra(itemnum); break;
- X case ME_SPECIAL:
- X handle_special(itemnum); break;
- X case ME_OPTIONS:
- X handle_options(itemnum, flags); break;
- X }
- X show_counts(); /* in case we've altered the number of points or faces */
- X}
- X
- X
- Xvoid handle_project(itemnum)
- Xint itemnum;
- X{
- X switch (itemnum)
- X {
- X case MI_LOAD: load_request(); refresh_all(); break;
- X case MI_SAVE: save_request(); break;
- X case MI_CLEAR: new(); break;
- X case MI_SAVE_DEF: save_defaults(); break;
- X case MI_ABOUT: about_help(); break;
- X case MI_QUIT:
- X if (changes)
- X {
- X if (!tell_user_changes()) break;
- X }
- X sys_exit("");
- X break;
- X }
- X}
- X
- X
- Xvoid handle_edit(itemnum, mflags)
- Xint itemnum;
- X{
- X int value = mflags;
- X
- X switch (itemnum)
- X {
- X case MI_CUT: break;
- X case MI_COPY: break;
- X case MI_PASTE: break;
- X case MI_DUPLICATE: duplicate(!flags.points_only); break;
- X case MI_ERASE: del_selected(); break;
- X case MI_SELECTALL: select_all(); break;
- X case MI_SELECTCON: select_connected(-1); break;
- X case MI_DESELECTALL: deselect_all(); break;
- X case MI_POINTSONLY: flags.points_only = value; break;
- X case MI_FACESONLY: flags.faces_only = value; break;
- X case MI_EXCLUSIVE: flags.exclusive_del = value; break;
- X }
- X}
- X
- X
- Xvoid handle_polyhedra(itemnum)
- Xint itemnum;
- X{
- X switch(itemnum)
- X {
- X case MI_GLOBE:
- X create_globe();
- X refresh_all();
- X break;
- X case 7:
- X break;
- X default:
- X create_poly(itemnum);
- X refresh_all();
- X break;
- X }
- X}
- X
- X
- Xvoid handle_special(itemnum)
- Xint itemnum;
- X{
- X char refresh = 0;
- X
- X switch (itemnum)
- X {
- X case MI_RESET_ZOOM:
- X reset_zoom();
- X convert_points();
- X refresh = 1;
- X break;
- X case MI_FREQUENCY: frequency(); refresh = 1; break;
- X case MI_CONNECT: break;
- X case MI_DUAL: find_dual(); refresh = 1; break;
- X case MI_UNFOLD: unfold(); break;
- X case MI_NORMALIZE: normalize(); refresh = 1; break;
- X case MI_STELLATE: stellate(); refresh = 1; break;
- X case MI_ORIGIN: center_to_origin(); refresh = 1; break;
- X case MI_SETCLOCK: set_clockwisdom(); break;
- X }
- X if (refresh) refresh_all();
- X}
- X
- X
- Xvoid handle_options(itemnum, mflags)
- Xint itemnum;
- XUSHORT mflags;
- X{
- X int value = mflags;
- X
- X switch (itemnum)
- X {
- X case MI_ASSUME_POLY:
- X flags.assume_poly = value;
- X break;
- X case MI_COORDS:
- X flags.show_coords = value;
- X draw_coords(!value); /* if value is 0, erase */
- X break;
- X case MI_CROSSHAIR:
- X flags.crosshair = value;
- X draw_hair();
- X break;
- X case MI_DISTANCETOOL:
- X toggle_dtool();
- X break;
- X case MI_ROTATEALL:
- X flags.rotate_all = value;
- X break;
- X case MI_UNDOBUF:
- X flags.undo_active = value;
- X init_undo();
- X break;
- X case MI_UNDOBUFSIZE:
- X get_undo_bufsize();
- X break;
- X }
- X}
- X
- X
- Xvoid add_all_menus()
- X{
- X add_menu("Project");
- X add_menu("Edit");
- X add_menu("Polyhedra");
- X add_menu("Special");
- X add_menu("Options");
- X
- X add_menu_item(0, "Load ", 0, 'O');
- X add_menu_item(0, "Save ", 0, 'S');
- X add_menu_item(0, "Clear ", 0, 0);
- X add_menu_item(0, "----", MO_NOTENABLED, 0);
- X add_menu_item(0, "Save defaults", 0, 0);
- X add_menu_item(0, "About/Help ", 0, 0);
- X add_menu_item(0, "----", MO_NOTENABLED, 0);
- X add_menu_item(0, "Quit ", 0, 'Q');
- X
- X add_menu_item(1, "Cut ", MO_NOTENABLED, 'X');
- X add_menu_item(1, "Copy ", MO_NOTENABLED, 'C');
- X add_menu_item(1, "Paste ", MO_NOTENABLED, 'V');
- X add_menu_item(1, "Duplicate ", 0, 'D');
- X add_menu_item(1, "Erase (Backspace)", 0, 0);
- X add_menu_item(1, "---------- ", MO_NOTENABLED, 0);
- X add_menu_item(1, "Select All (Esc Esc)", 0, 0);
- X add_menu_item(1, "Select Connected ", 0, 0);
- X add_menu_item(1, "Deselect All (Esc)", 0, 0);
- X add_menu_item(1, "---------- ", MO_NOTENABLED, 0);
- X add_menu_item(1, "Points Only? ", MO_TOGGLE, 0);
- X add_menu_item(1, "Faces/Polys Only?", MO_TOGGLE, 0);
- X add_menu_item(1, "Exclusive Delete?", MO_TOGGLE | MO_CHECKED, 0);
- X
- X add_menu_item(2, "Tetrahedron ", 0, 0);
- X add_menu_item(2, "Octahedron ", 0, 0);
- X add_menu_item(2, "Cube ", 0, 0);
- X add_menu_item(2, "Icosahedron ", 0, 0);
- X add_menu_item(2, "Dodecahedron ", 0, 0);
- X add_menu_item(2, " (rhombic) ", 0, 0);
- X add_menu_item(2, "Cuboctahedron", 0, 0);
- X add_menu_item(2, "-------------", MO_NOTENABLED, 0);
- X add_menu_item(2, "Globe ", 0, 0);
- X add_menu_item(2, "Surf. of Rev.", MO_NOTENABLED, 0);
- X
- X add_menu_item(3, "Reset Zoom ", 0, 'R');
- X add_menu_item(3, "Frequency ", 0, 'F');
- X add_menu_item(3, "Connect 'em ", MO_NOTENABLED, 0);
- X add_menu_item(3, "Find Dual ", 0, 'D');
- X add_menu_item(3, "Unfold ", MO_NOTENABLED, 0);
- X add_menu_item(3, "Normalize ", 0, 'N');
- X add_menu_item(3, "Stellate ", 0, 0);
- X add_menu_item(3, "Center -> Origin ", 0, 0);
- X add_menu_item(3, "Set Clockwisdom ", 0, 0);
- X
- X add_menu_item(4, "Assume Polyhedron? ", MO_TOGGLE | (flags.assume_poly ? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Display Coords? ", MO_TOGGLE | (flags.show_coords ? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Display Crosshair? (c)", MO_TOGGLE | (flags.crosshair ? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Distance Tool? (d)", MO_TOGGLE | (flags.display_dtool? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Rotate Everything? ", MO_TOGGLE | (flags.rotate_all ? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Undo Buffer Active? ", MO_TOGGLE | (flags.undo_active ? MO_CHECKED : 0), 0);
- X add_menu_item(4, "Set Undo Buffer Size ", 0, 0);
- X
- X sys_attach_menus();
- X}
- X
- X
- Xvoid add_all_gadgets()
- X{
- X add_gadget("ADD", 0);
- X add_gadget("DELETE", 0);
- X add_gadget("SELECTOR", 0);
- X add_gadget("MOVE", 0);
- X add_gadget("FACE", 0);
- X add_gadget("POLY", 0);
- X add_gadget(" (more)", GF_NOSELECT);
- X add_gadget("DEFACE", 0);
- X add_gadget("DEPOLY", 0);
- X add_gadget(" (more)", GF_NOSELECT);
- X add_gadget("ROTATE", 0);
- X add_gadget("(rotate)", GF_NOSELECT);
- X add_gadget("ZOOM", 0);
- X add_gadget("DISTANCE", 0);
- X add_gadget("GLUE", 0);
- X add_gadget("UNDO", 0);
- X add_gadget("REDO", 0);
- X add_gadget("XY front", 0);
- X add_gadget("XZ top", 0);
- X add_gadget("ZY side ", 0);
- X add_gadget("> 3D <", GF_NOSELECT);
- X add_gadget("color1", 0);
- X add_gadget("color2", 0);
- X add_gadget("color3", 0);
- X
- X sys_refresh_gadgets();
- X}
- X
- X
- Xsave_data(fname)
- Xchar *fname;
- X{
- X uindex i, j;
- X FILE *fp;
- X
- X if (!points) return ERR_NOTHING;
- X fp = fopen(fname, "w");
- X if (!fp) return ERR_CANTOPEN;
- X
- X fprintf(fp, "#simple 3D file\n");
- X fprintf(fp, "points %d\n", points);
- X fprintf(fp, "faces %d\n", faces);
- X fprintf(fp, "polys %d\n", polys);
- X
- X /* save points */
- X fprintf(fp, "\n# points are stored as \"point X Y Z\"\n\n");
- X for (i = 0; i < points; i++)
- X#if INTEGER
- X fprintf(fp, "point %d %d %d\n", point[i].x, point[i].y, point[i].z);
- X#else
- X fprintf(fp, "point %lf %lf %lf\n", point[i].x, point[i].y, point[i].z);
- X#endif
- X
- X /* save faces */
- X if (faces)
- X {
- X fprintf(fp, "\n# faces are stored as \"face p0 p1 p2 color\"\n\n");
- X for (i = 0; i < faces; i++)
- X fprintf(fp, "face %d %d %d %d\n",
- X face[i].p[0], face[i].p[1], face[i].p[2], face[i].color);
- X }
- X
- X /* save polygons */
- X if (polys)
- X {
- X fprintf(fp, "\n# polygons are stored as \"poly N p1 ... pN color\"\n\n");
- X for (i = 0; i < polys; i++)
- X {
- X fprintf(fp, "poly %d ", poly[i].verts);
- X for (j = 0; j < poly[i].verts; j++)
- X fprintf(fp, "%d ", poly[i].p[j]);
- X fprintf(fp, "%d\n", poly[i].color);
- X }
- X }
- X fprintf(fp, "\n");
- X fclose(fp);
- X return OKAY;
- X}
- X
- X
- Xload_data(fname)
- Xchar *fname;
- X{
- X FILE *fp;
- X int j, k[MAX_EDGES];
- X coord x_lo, y_lo, z_lo,
- X x_hi, y_hi, z_hi,
- X x_size, y_size, z_size,
- X greatest;
- X char buf[128]; /* maximum line length */
- X uindex i;
- X#if INTEGER
- X int x, y, z;
- X#else
- X double x, y, z;
- X#endif
- X
- X if (!(fp = fopen(fname, "r")))
- X return ERR_CANTOPEN;
- X
- X fgets(buf, 85, fp); /* Read first line */
- X if (strncmp(buf, "#simple 3D file", 15))
- X return ERR_NOTED3;
- X
- X for (i = 0; i < 3; i++)
- X {
- X fgets(buf, 85, fp);
- X if (*buf == 0) break;
- X if (!strncmp(buf, "points ", 7))
- X {
- X sscanf(buf, "points %d\n", &j);
- X
- X /* see if this value is OK */
- X if (!j)
- X {
- X fclose(fp);
- X return ERR_NOTHING;
- X }
- X if (j >= MAX_POINTS)
- X {
- X if (more_points(j + 100))
- X {
- X printf("unable to make room for %d points.\n", j);
- X fclose(fp);
- X return ERR_NOMEM_POINT;
- X }
- X }
- X }
- X if (!strncmp(buf, "faces ", 7))
- X {
- X fscanf(fp, "faces %d\n", &j);
- X if (j >= MAX_FACES)
- X {
- X if (more_faces(j + 100))
- X {
- X fclose(fp);
- X return ERR_NOMEM_FACE;
- X }
- X }
- X }
- X if (!strncmp(buf, "polys ", 7))
- X {
- X fscanf(fp, "polys %d\n", &j);
- X if (j >= MAX_POLYS)
- X {
- X if (more_polys(j + 100))
- X {
- X fclose(fp);
- X return ERR_NOMEM_POLY;
- X }
- X }
- X }
- X }
- X
- X /* in case the object is much larger or smaller than the screen, we need
- X to adjust our scaling based on the bounding box of the data */
- X x_lo = y_lo = z_lo = x_hi = y_hi = z_hi = 0;
- X faces = points = polys = 0;
- X
- X while (fgets(buf, 85, fp) != NULL)
- X {
- X if (!strncmp(buf, "face ", 5))
- X {
- X sscanf(buf + 5, "%d %d %d %d", &k[0], &k[1], &k[2], &k[3]);
- X if (k[0] >= points || k[1] >= points || k[2] >= points)
- X {
- X fclose(fp);
- X return ERR_BADFACE;
- X }
- X add_face0(k[0], k[1], k[2], k[3]);
- X }
- X else if (!strncmp(buf, "poly ", 5))
- X {
- X sscanf(buf + 5, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
- X k+0, k+1, k+2, k+3, k+4, k+5, k+6, k+7, k+8, k+9,
- X k+10, k+11, k+12, k+13, k+14, k+15, k+16, k+17, k+18, k+19, k+20);
- X allocate_poly(k[0], k[k[0]+1]);
- X for (i = 0; i < k[0]; i++)
- X poly[polys].p[i] = k[i+1];
- X finish_poly(1);
- X }
- X else if (!strncmp(buf, "point ", 6))
- X {
- X#if INTEGER
- X sscanf(buf + 6, "%d %d %d", &x, &y, &z);
- X#else
- X sscanf(buf + 6, "%lf %lf %lf", &x, &y, &z);
- X#endif
- X if (x < x_lo) x_lo = x;
- X if (x > x_hi) x_hi = x;
- X if (y < y_lo) y_lo = y;
- X if (y > y_hi) y_hi = y;
- X if (z < z_lo) z_lo = z;
- X if (z > z_hi) z_hi = z;
- X add_point0(x, y, z);
- X }
- X else if (*buf && *buf != '#' && *buf != '\n')
- X {
- X printf("Don't understand line: %s", buf);
- X }
- X }
- X
- X x_size = max(-x_lo, x_hi); /* since coordinates are always centered */
- X y_size = max(-y_lo, y_hi);
- X z_size = max(-z_lo, z_hi);
- X greatest = max(x_size, y_size);
- X greatest = max(greatest, z_size);
- X
- X /* scale = units per pixel. Here, "greatest" is the most units
- X that half the screen must accomodate */
- X SCALE = (double)greatest / (double)(symax >> 1) * 1.1;
- X
- X fclose(fp);
- X convert_points();
- X return OKAY;
- X}
- X
- X
- Xvoid get_undo_bufsize()
- X{
- X long new_ab = act_buf;
- X long new_ob = op_buf;
- X int go = 1, ok = 1, event;
- X int id;
- X long data;
- X
- X sys_window(34, 4, "Set Undo Buffer Size");
- X sys_movecur(7,0);
- X sys_say_text("Size in bytes:");
- X sys_get_long(new_ab, 1);
- X sys_movecur(1,1);
- X sys_say_text("Maximum undo levels:");
- X sys_get_long(new_ob, 2);
- X sys_movecur(7,2);
- X sys_boolean(" OK ", 3);
- X sys_movecur(17,2);
- X sys_boolean("Cancel", 4);
- X sys_activate(1);
- X
- X while (go)
- X {
- X event = sys_read_event(&id, &data);
- X switch (event)
- X {
- X case EV_CANCEL:
- X go = 0;
- X break;
- X case EV_CHECKINT:
- X/* printf("checkint gadget %d, data %ld\n", id, data); */
- X case EV_HITRETURN:
- X/* if (event == EV_HITRETURN) printf("hit return on gadget %d, data %ld\n", id, data); */
- X if (id == 1)
- X {
- X if (data > 32000) data = 32000;
- X if (data < 1000) data = 1000;
- X new_ab = data;
- X if (event == EV_HITRETURN) sys_activate(2);
- X }
- X if (id == 2)
- X {
- X if (data > 2000) data = 2000;
- X if (data < 10) data = 10;
- X new_ob = data;
- X if (event == EV_HITRETURN) { go = 0; ok = 1; }
- X }
- X break;
- X case EV_HITBUTTON:
- X/* printf("hit button on gadget %d, data %ld\n", id, data); */
- X if (id == 3) { go = 0; ok = 1; }
- X else { go = 0; ok = 0; }
- X break;
- X }
- X }
- X if (ok)
- X {
- X act_buf = new_ab;
- X op_buf = new_ob;
- X }
- X sys_close_window();
- X}
- X
- X
- X/* Tell the user that the requested operation will overflow the undo buffer. */
- X/* Returns TRUE if the user decides to turn off undo and proceed anyway. */
- X
- Xint tell_user_overflow()
- X{
- X int id, event;
- X long data;
- X
- X sys_window(45, 6, "Warning!");
- X sys_movecur(0,0);
- X sys_say_text("The operation you requested will overflow");
- X sys_movecur(0,1);
- X sys_say_text("the undo buffer. Do you wish to turn undo");
- X sys_movecur(0,2);
- X sys_say_text("off and proceed, or cancel the operation?");
- X sys_movecur(1,4);
- X sys_boolean("Turn off and proceed", 1);
- X sys_say_text(" ");
- X sys_boolean("Cancel operation", 2);
- X
- X while (1)
- X {
- X event = sys_read_event(&id, &data);
- X switch (event)
- X {
- X case EV_HITBUTTON:
- X if (id == 1)
- X {
- X flags.undo_active = 0;
- X toggle_menuitem(ME_OPTIONS, MI_UNDOBUF);
- X init_undo();
- X sys_close_window();
- X return 1;
- X }
- X case EV_CANCEL:
- X sys_close_window();
- X return 0; /* cancel operation */
- X break;
- X }
- X }
- X}
- X
- X
- X/* Warn the user that there are unsaved changed */
- X/* returns TRUE if the user say its OK to continue */
- X
- Xint tell_user_changes()
- X{
- X char buf[20];
- X int go = 1, ok = 1, event;
- X int id;
- X long data;
- X
- X sys_window(37, 5, "Warning: Unsaved Changes!");
- X sys_movecur(1,0);
- X sys_say_text("You have made");
- X sprintf(buf, " %d ", changes);
- X sys_say_text(buf);
- X sys_say_text("unsaved ");
- X sys_say_text((changes < -1 || changes > 1) ? "changes." : "change.");
- X sys_movecur(1,1);
- X sys_say_text((changes < -1 || changes > 1) ? "They" : "It");
- X sys_say_text(" will be lost if you continue!");
- X
- X sys_movecur(4,3);
- X sys_boolean("OK - continue", 1);
- X sys_movecur(20,3);
- X sys_boolean("Cancel!", 2);
- X
- X while (go)
- X {
- X event = sys_read_event(&id, &data);
- X switch (event)
- X {
- X case EV_HITBUTTON:
- X if (id == 1) { go = 0; ok = 1; break; }
- X case EV_CANCEL:
- X go = 0;
- X ok = 0;
- X break;
- X }
- X }
- X sys_close_window();
- X return (ok);
- X}
- X
- X
- X/* Tell the user about ed3, and provide a little help. */
- X
- Xvoid about_help()
- X{
- X int go = 1, ok = 1, event;
- X int id;
- X long data;
- X
- X sys_window(59, 13, "About ED3 - and some Help");
- X sys_movecur(0,0);
- X sys_say_text("ED3 is a 3D object editor placed in the public domain by");
- X sys_movecur(0,1);
- X sys_say_text("its author, Ben Discoe. That means I didn't copyright it");
- X sys_movecur(0,2);
- X sys_say_text("and neither can you. Information should be free, y'all.");
- X sys_movecur(0,3);
- X#if INTEGER
- X sys_say_text("This is the integer version. A floating-point version");
- X#else
- X sys_say_text("This is the floating-point version. An integer version");
- X#endif
- X sys_movecur(0,4);
- X sys_say_text("is also available. The source is freely available.");
- X sys_movecur(0,5);
- X sys_say_text("\"Faces\" refer to triangles, and \"Polys\" refer to");
- X sys_movecur(0,6);
- X sys_say_text("polygons with more than 3 sides. This distinction is made");
- X sys_movecur(0,7);
- X sys_say_text("for reasons of efficiency. Undo/Redo is available and is");
- X sys_movecur(0,8);
- X sys_say_text("limited only by the amount of memory you give it.");
- X sys_movecur(0,9);
- X sys_say_text("To learn the special features, experiment!");
- X
- X sys_movecur(12,11);
- X sys_boolean(" OK ", 1);
- X sys_movecur(28,11);
- X sys_boolean("Keyboard Shortcuts", 2);
- X
- X while (go)
- X {
- X event = sys_read_event(&id, &data);
- X switch (event)
- X {
- X case EV_HITBUTTON:
- X if (id == 2) { go = 0; ok = 0; break; }
- X case EV_CANCEL:
- X go = 0;
- X ok = 1;
- X break;
- X }
- X }
- X sys_close_window();
- X if (ok) return;
- X
- X sys_window(57, 6, "Keyboard Shortcuts");
- X sys_movecur(0,0);
- X sys_say_text(" c - toggle crosshair Esc - deselect/select All");
- X sys_movecur(0,1);
- X sys_say_text(" d - toggle distance-tool a - zoom in");
- X sys_movecur(0,2);
- X sys_say_text(" m - Move mode z - zoom out");
- X sys_movecur(0,3);
- X sys_say_text(" u - undo backspace - kill selected");
- X sys_movecur(0,4);
- X sys_say_text(" r - redo space bar - full refresh");
- X sys_movecur(22,5);
- X sys_boolean(" OK ", 1);
- X
- X go = 1;
- X while (go)
- X {
- X event = sys_read_event(&id, &data);
- X switch (event)
- X {
- X case EV_HITBUTTON:
- X case EV_CANCEL:
- X go = 0;
- X break;
- X }
- X }
- X sys_close_window();
- X}
- X
- X
- Xvoid save_request()
- X{
- X char *fname;
- X int status;
- X
- X fname = sys_file_requestor("Save 3D file", "*.3d");
- X if (! *fname) return;
- X
- X if (status = save_data(fname))
- X SimpleRequest("Problem saving: %s.", errstring[status]);
- X}
- X
- X
- Xvoid load_request()
- X{
- X char *fname;
- X int status;
- X
- X fname = sys_file_requestor("Load 3D file", "*.3d");
- X if (! *fname) return;
- X
- X if (status = load_data(fname))
- X SimpleRequest("Problem loading: %s.", errstring[status]);
- X}
- X
- X
- Xsave_defaults()
- X{
- X FILE *fp;
- X
- X fp = fopen("ed3-defs", "w");
- X if (!fp) return ERR_CANTOPEN;
- X
- X fprintf(fp, "%d ", flags.assume_poly);
- X fprintf(fp, "%d ", flags.display_dtool);
- X fprintf(fp, "%d ", flags.show_coords);
- X fprintf(fp, "%d ", flags.crosshair);
- X fprintf(fp, "%d ", flags.rotate_all);
- X fprintf(fp, "%d ", flags.undo_active);
- X fprintf(fp, "%d ", act_buf);
- X fprintf(fp, "%d ", op_buf);
- X
- X fclose(fp);
- X return OKAY;
- X}
- X
- X
- Xload_defaults()
- X{
- X FILE *fp;
- X int i1, i2, i3, i4;
- X
- X fp = fopen("ed3-defs", "r");
- X if (!fp) return ERR_CANTOPEN;
- X
- X /* we must scanf indirectly because the destination variables may
- X not be ints */
- X
- X fscanf(fp, "%d ", &i1);
- X fscanf(fp, "%d ", &i2);
- X fscanf(fp, "%d ", &i3);
- X fscanf(fp, "%d ", &i4);
- X
- X flags.assume_poly = i1;
- X flags.display_dtool = i2;
- X flags.show_coords = i3;
- X flags.crosshair = i4;
- X
- X fscanf(fp, "%d ", &i1);
- X fscanf(fp, "%d ", &i2);
- X fscanf(fp, "%d ", &i3);
- X fscanf(fp, "%d ", &i4);
- X
- X flags.rotate_all = i1;
- X flags.undo_active = i2;
- X act_buf = i3;
- X op_buf = i4;
- X
- X fclose(fp);
- X return OKAY;
- X}
- X
- X
- END_OF_FILE
- if test 24785 -ne `wc -c <'edio.c'`; then
- echo shar: \"'edio.c'\" unpacked with wrong size!
- fi
- # end of 'edio.c'
- fi
- if test -f 'freq.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'freq.c'\"
- else
- echo shar: Extracting \"'freq.c'\" \(19873 characters\)
- sed "s/^X//" >'freq.c' <<'END_OF_FILE'
- X/*
- X This module of of ed3 devoted to raising polyhedra to
- X higher frequencies.
- X
- X10-13-91 frequency() now checks to see if there is room in the undo buf
- X09-19-91 found tiny bug (missing a -1) on line 385. It caused glitches.
- X08-26-91 fixed small (final?) bug in freq algo
- X08-24-91 attempt to extend algorithm to quadrilaterals.
- X We could try to do this by doubling the complexity of the
- X current code (same size, double complex) or by doubling
- X the size. Having a second type of shape (quads) could mean
- X 4 times the complexity (n^2 effect!).
- X*/
- X
- X#include "sysnogr.h"
- X
- X
- X/* freq = 1 freq = 2 freq = 3 etc.
- X A A A
- X / \ / \ / \
- X / \ / \ 0---1
- X / \ -> 0-----1 -> / \ / \ ->
- X / \ / \ / \ 2---3---4
- X / \ / \ / \ / \ / \ / \
- X B-----------C B-----2-----C B---5---6---C
- X
- X This algorithm is careful not to duplicate the (already existing)
- X vertices of the current triangles. It should also not duplicate the
- X frequency edge vertices of adjacent faces. Note that this algorithm
- X will work for ANY frequency, however frequencies beyond 5 would
- X require recompiling with a larger second dimension to the edge_point
- X array in FaceInfo, to hold more edge points. Rotation sense of the
- X triangle's points is maintained (same as the original triangle).
- X
- XAdded on 8-24-91: Quadrilateral support!
- X
- X freq = 1 freq = 2 freq = 3
- X
- X A A A
- X / \ / \ / \
- X / \ / \ / 0
- X / \ / 0 / \
- X / \ / / \ 2 1
- X / \ / / \ / 3 \
- X / D 1- | D / D
- X / | / \- / | / 4 |
- X / | / \2--- | 6 7 5
- X / | / | \--3 / 8 |
- X / | / / | / 9
- X / | / | | / |
- XB-----------------C B--------4--------C B---10---11---12--C
- X
- X
- X Quadrilaterals divide into the same number of sections as triangles, but
- Xrequire more points to do so. Quad support was added so that you can do
- Xfrequency operations on cuboctahedrons, cubes, rhombic dodecahedrons, etc.
- X
- X*/
- X
- X
- Xstruct FaceInfo { /* info that each face needs to know */
- X uindex index[3]; /* concerning what faces are adjacent */
- X short kind[3]; /* which kind of shape is adjacent */
- X unsigned present : 3, /* IF there is one */
- X direction : 3, /* HOW: 0 is normal, 1 is reverse */
- X edge : 6; /* WHICH edge of the adjacent face */
- X uindex edge_point[3][4];/* allows up to freq. 5: [3][f-1] */
- X};
- X
- Xstruct QuadInfo { /* info that each 4-sided poly needs to know */
- X uindex poly; /* the index of the corresponding polygon */
- X uindex index[4]; /* concerning what faces are adjacent */
- X short kind[4]; /* which kind of shape is adjacent */
- X unsigned present : 4, /* IF there is one */
- X direction : 4, /* HOW: 0 is normal, 1 is reverse */
- X edge : 8; /* WHICH edge of the adjacent face */
- X uindex edge_point[4][4];/* allows up to freq. 5: [4][f-1] */
- X};
- X
- X/* values for the "kind" field in the above structures */
- X#define K_FACE 1
- X#define K_QUAD 2
- X
- X
- Xvoid frequency()
- X{
- X int id, freq, err, event;
- X int go = 1;
- X int quads, add_p, add_f, del_f, add_q, del_q;
- X index po0;
- X
- X freq = 3;
- X sys_window(34, 2, "Tesselate Polyhedron");
- X sys_movecur(1,0);
- X sys_say_text("to Frequency (2..7):");
- X sys_get_long(freq, 1);
- X sys_activate(1);
- X
- X while (go)
- X {
- X event = sys_read_event(&id, &freq);
- X switch (event)
- X {
- X case EV_CANCEL:
- X sys_close_window();
- X return;
- X break;
- X case EV_CHECKINT:
- X case EV_HITRETURN:
- X if (freq > 7) freq = 7;
- X if (freq < 2) freq = 2;
- X if (event == EV_HITRETURN) go = 0;
- X break;
- X }
- X }
- X sys_close_window();
- X
- X /* Estimate how many actions the tesselation will require. */
- X /* Assume the worst case of all facets non-adjacent */
- X /* count how many quads we've got */
- X quads = 0;
- X for (po0 = 0; po0 < polys; po0++)
- X if (poly[po0].verts == 4) quads++;
- X add_p = faces * (fibo(freq + 1) - 3); /* for the faces */
- X add_p += quads * ((freq * freq) - 4); /* for the quads */
- X add_f = faces * freq * freq;
- X del_f = faces;
- X add_q = quads * freq * freq;
- X del_q = quads;
- X
- X /* Make sure that this event won't overflow the undo buffer */
- X if (!enough_room(add_p, add_f, add_q, 0, del_f, del_q, 0, 4))
- X {
- X /* this operation will overflow the undo buffer! */
- X if (!tell_user_overflow()) return;
- X }
- X
- X begin_operation();
- X err = bucky_frequency(freq);
- X end_operation();
- X}
- X
- X
- Xbucky_frequency(freq)
- Xshort freq;
- X{
- X index f, f2; /* each face, signed for backwards loop */
- X index q, q2; /* each quad, signed for backwards loop */
- X index fpoint[21]; /* allows frequencies of up to 5: (f+1)(f+2)/2 */
- X index fpoints; /* temporary indices for current face triangle */
- X index qpoint[42]; /* allows frequencies of up to 5: (f+1)(f+2) */
- X index qpoints; /* temporary indices for current quad */
- X index prev; /* index of point at start of last row */
- X index row, i; /* loops */
- X uindex p0, p1, p2, p3;
- X uindex e, e2; /* edges */
- X Point3D vec[3], /* 2 or 3 edge vectors, face or quad */
- X start, /* coordinates of the start of each row */
- X end; /* (for quads) coords of the end of each row */
- X uindex old_faces = faces;
- X uindex old_polys = polys;
- X struct FaceInfo *finfo = 0L, fcurrent;
- X struct QuadInfo *qinfo = 0L, qcurrent;
- X uindex adj_face, adj_quad, adj_edge, pos;
- X char add_the_point, flag;
- X index po0, po1; /* polygon counter */
- X index quads;
- X
- X /* count how many quads we've got */
- X quads = 0;
- X for (po0 = 0; po0 < polys; po0++)
- X if (poly[po0].verts == 4) quads++;
- X
- X if (!faces && !quads) return OKAY; /* must have SOMETHING to operate on */
- X
- X if (freq < 2 || freq > 20) return OKAY;
- X
- X /* we need to allocate memory, since the number of faces is variable */
- X if (faces)
- X {
- X if (flags.debug)
- X printf("allocating %d bytes for faces\n", faces*sizeof(struct FaceInfo));
- X finfo = (struct FaceInfo *)sys_alloc(faces*sizeof(struct FaceInfo));
- X if (!finfo)
- X {
- X screen_say("Not enough memory for that frequency");
- X return ERR_NOMEM;
- X }
- X }
- X if (quads)
- X {
- X if (flags.debug)
- X printf("allocating %d bytes for quads\n", quads*sizeof(struct QuadInfo));
- X qinfo = (struct QuadInfo *)sys_alloc(quads*sizeof(struct QuadInfo));
- X if (!qinfo)
- X {
- X screen_say("Not enough memory for that frequency");
- X return ERR_NOMEM;
- X }
- X }
- X
- X /* we need to link our QuadInfo structures with real polygons */
- X quads = 0;
- X for (po0 = 0; po0 < polys; po0++)
- X if (poly[po0].verts == 4)
- X qinfo[quads++].poly = po0;
- X
- X if (flags.debug) printf("frequency %d\n", freq);
- X
- X/* Before triangulating, we scan all the faces and quads and assign each edge
- X a "master" face/quad that "owns" that edge. Later, only this face/quad
- X will add vertice points along this edge. The last face/quad will always
- X add all it's edges.
- X*/
- X
- X for (f = 0; f < faces; f++)
- X {
- X finfo[f].present = 0; /* by default, DO add the edge. */
- X finfo[f].direction = 0;
- X finfo[f].edge = 0;
- X
- X/**** Compare faces against faces */
- X
- X for (f2 = f+1; f2 < faces; f2++)
- X {
- X for (e = 0; e < 3; e++)
- X {
- X p0 = face[f].p[e];
- X p1 = face[f].p[(e+1)%3];
- X
- X for (e2 = 0; e2 < 3; e2++)
- X {
- X /* There are two ways that one edge can match another:
- X the point numbers can be identical or inverted.
- X Edge i has indices i, (i+1)%3 for i = 0,1,2.
- X */
- X p2 = face[f2].p[e2];
- X p3 = face[f2].p[(e2+1)%3];
- X flag = 0;
- X if (p0 == p2 && p1 == p3)
- X {
- X flag = 1;
- X }
- X else if (p0 == p3 && p1 == p2)
- X {
- X finfo[f].direction |= 1<<e;
- X flag = 1;
- X }
- X if (flag)
- X {
- X finfo[f].present |= 1<<e;
- X finfo[f].kind[e] = K_FACE;
- X finfo[f].index[e] = f2;
- X finfo[f].edge |= (e2 << (e << 1));
- X break;
- X }
- X }
- X }
- X }
- X
- X/**** Compare faces against quads */
- X
- X for (q2 = 0; q2 < quads; q2++)
- X {
- X po1 = qinfo[q2].poly;
- X for (e = 0; e < 3; e++)
- X {
- X p0 = face[f].p[e];
- X p1 = face[f].p[(e+1)%3];
- X
- X for (e2 = 0; e2 < 4; e2++)
- X {
- X p2 = poly[po1].p[e2];
- X p3 = poly[po1].p[(e2+1)%4];
- X flag = 0;
- X if (p0 == p2 && p1 == p3)
- X {
- X flag = 1;
- X }
- X else if (p0 == p3 && p1 == p2)
- X {
- X finfo[f].direction |= 1<<e;
- X flag = 1;
- X }
- X if (flag)
- X {
- X finfo[f].present |= 1<<e;
- X finfo[f].kind[e] = K_QUAD;
- X finfo[f].index[e] = q2;
- X finfo[f].edge |= (e2 << (e << 1));
- X break;
- X }
- X }
- X }
- X }
- X }
- X
- X/**** Compare quads against quads */
- X
- X for (q = 0; q < quads-1; q++)
- X {
- X qinfo[q].present = 0; /* by default, DO add the edge. */
- X qinfo[q].direction = 0;
- X qinfo[q].edge = 0;
- X po0 = qinfo[q].poly;
- X
- X for (q2 = q+1; q2 < quads; q2++)
- X {
- X po1 = qinfo[q2].poly;
- X for (e = 0; e < 4; e++)
- X {
- X p0 = poly[po0].p[e];
- X p1 = poly[po0].p[(e+1)%4];
- X
- X for (e2 = 0; e2 < 4; e2++)
- X {
- X p2 = poly[po1].p[e2];
- X p3 = poly[po1].p[(e2+1)%4];
- X flag = 0;
- X if (p0 == p2 && p1 == p3)
- X {
- X flag = 1;
- X }
- X else if (p0 == p3 && p1 == p2)
- X {
- X qinfo[q].direction |= 1<<e;
- X flag = 1;
- X }
- X if (flag)
- X {
- X qinfo[q].present |= 1<<e;
- X qinfo[q].kind[e] = K_QUAD;
- X qinfo[q].index[e] = q2;
- X qinfo[q].edge |= (e2 << (e << 1));
- X break;
- X }
- X }
- X }
- X }
- X }
- X /* the last quad is always MASTER! AH ha ha! */
- X if (quads) qinfo[quads-1].present = 0;
- X
- X/*********************************************/
- X/** PHASE 2: the tesselation process itself. */
- X/*********************************************/
- X
- X/*** Quads first! */
- X
- X for (q = quads-1; q >= 0; q--) /* count down through faces */
- X {
- X qpoints = 0;
- X po0 = qinfo[q].poly;
- X p0 = poly[po0].p[0];
- X p1 = poly[po0].p[1];
- X p2 = poly[po0].p[2];
- X p3 = poly[po0].p[3];
- X qcurrent = qinfo[q];
- X
- X /* form the vectors A->B and D->C */
- X vec[0].x = point[p1].x - point[p0].x;
- X vec[0].y = point[p1].y - point[p0].y;
- X vec[0].z = point[p1].z - point[p0].z;
- X vec[1].x = point[p2].x - point[p3].x;
- X vec[1].y = point[p2].y - point[p3].y;
- X vec[1].z = point[p2].z - point[p3].z;
- X
- X for (row = 0; row <= freq; row++) /* there are frequency+1 rows */
- X {
- X /* prev is the index at the start of the previous row */
- X prev = (row * (row-1)) / 2;
- X
- X start.x = point[p0].x + (row * vec[0].x / freq);
- X start.y = point[p0].y + (row * vec[0].y / freq);
- X start.z = point[p0].z + (row * vec[0].z / freq);
- X
- X end.x = point[p3].x + (row * vec[1].x / freq);
- X end.y = point[p3].y + (row * vec[1].y / freq);
- X end.z = point[p3].z + (row * vec[1].z / freq);
- X
- X vec[2].x = end.x - start.x;
- X vec[2].y = end.y - start.y;
- X vec[2].z = end.z - start.z;
- X
- X/** handle left edge */
- X /* the corners are special cases */
- X if (row == 0)
- X qpoint[qpoints++] = p0; /* top */
- X else if (row == freq)
- X qpoint[qpoints++] = p1; /* bottom left */
- X else
- X {
- X /* This is the first side (point 0 to point 1) */
- X if (qcurrent.present & 1)
- X {
- X if (qcurrent.kind[0] == K_QUAD)
- X {
- X /* these edge points belong to another quad */
- X adj_quad = qcurrent.index[0];
- X adj_edge = (qcurrent.edge & 3);
- X pos = (qcurrent.direction & 1 ? freq-row-1 : row-1);
- X qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else sys_exit("fatal error 1"); /* should never occur! */
- X }
- X else
- X {
- X /* these edge points belong to THIS face; create point */
- X qpoint[qpoints++] = points;
- X qinfo[q].edge_point[0][row-1] = points;
- X add_point(start.x, start.y, start.z);
- X }
- X }
- X
- X/** move across, left to right */
- X for (i = 1; i <= freq; i++)
- X {
- X add_the_point = 0;
- X
- X /* This point may be the bottom corner */
- X if (row == freq && i == freq) qpoint[qpoints++] = p2;
- X
- X /* Or the upper right corner */
- X else if (row == 0 && i == freq) qpoint[qpoints++] = p3;
- X
- X /* or it's the second side (point 1 to point 2) */
- X else if (row == freq && i != freq)
- X {
- X if (qcurrent.present & 2) /* the edge exists */
- X {
- X adj_quad = qcurrent.index[1];
- X adj_edge = (qcurrent.edge >> 2) & 3;
- X pos = (qcurrent.direction & 2 ? freq-i-1 : i-1);
- X qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else /* the edge must be created */
- X {
- X qinfo[q].edge_point[1][i-1] = points;
- X add_the_point = 1;
- X }
- X }
- X
- X /* or it's the third side (point 2 to point 3) */
- X else if (row != 0 && row != freq && i == freq)
- X {
- X if (qcurrent.present & 4) /* the edge exists */
- X {
- X adj_quad = qcurrent.index[2];
- X adj_edge = (qcurrent.edge >> 4) & 3;
- X /* the following is backwards: subtle note below */
- X pos = (qcurrent.direction & 4 ? row-1 : freq-row-1);
- X qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else /* the edge is created and specially numbered */
- X {
- X /* subtle point: we must be careful that the edge
- X vertices are entered in the same clockwisdom
- X as the vector point2->point0 */
- X qinfo[q].edge_point[2][freq-row-1] = points;
- X add_the_point = 1;
- X }
- X }
- X
- X /* or it's the fourth side (point 3 to point 0) */
- X else if (row == 0 && i != freq)
- X {
- X if (qcurrent.present & 8) /* the edge exists */
- X {
- X adj_quad = qcurrent.index[3];
- X adj_edge = (qcurrent.edge >> 6) & 3;
- X /* the following is backwards: subtle note below */
- X pos = (qcurrent.direction & 8 ? i-1 : freq-i-1);
- X qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else /* the edge is created and specially numbered */
- X {
- X /* subtle point: we must be careful that the edge
- X vertices are entered in the same clockwisdom
- X as the vector point2->point0 */
- X qinfo[q].edge_point[3][freq-i-1] = points;
- X add_the_point = 1;
- X }
- X }
- X
- X /* otherwise, it's a point in the middle we need to create */
- X else add_the_point = 1;
- X
- X if (add_the_point)
- X {
- X qpoint[qpoints++] = points;
- X add_point(start.x + (i * vec[2].x / freq),
- X start.y + (i * vec[2].y / freq),
- X start.z + (i * vec[2].z / freq));
- X }
- X if (row != 0)
- X {
- X allocate_poly(4, colors.newface);
- X poly[polys].p[0] = qpoint[(row-1)*(freq+1)+i-1];
- X poly[polys].p[1] = qpoint[ row *(freq+1)+i-1];
- X poly[polys].p[2] = qpoint[ row *(freq+1)+i ];
- X poly[polys].p[3] = qpoint[(row-1)*(freq+1)+i ];
- X finish_poly(0);
- X }
- X }
- X }
- X }
- X
- X/********* now do the faces */
- X
- X for (f = faces-1; f >= 0; f--) /* count down through faces */
- X {
- X fpoints = 0;
- X p0 = face[f].p[0];
- X p1 = face[f].p[1];
- X p2 = face[f].p[2];
- X fcurrent = finfo[f];
- X
- X /* form the vectors A->B and B->C */
- X vec[0].x = point[p1].x - point[p0].x;
- X vec[0].y = point[p1].y - point[p0].y;
- X vec[0].z = point[p1].z - point[p0].z;
- X vec[1].x = point[p2].x - point[p1].x;
- X vec[1].y = point[p2].y - point[p1].y;
- X vec[1].z = point[p2].z - point[p1].z;
- X
- X for (row = 0; row <= freq; row++) /* there are frequency+1 rows */
- X {
- X /* prev is the index at the start of the previous row */
- X prev = (row * (row-1)) >> 1;
- X
- X start.x = point[p0].x + (row * vec[0].x / freq);
- X start.y = point[p0].y + (row * vec[0].y / freq);
- X start.z = point[p0].z + (row * vec[0].z / freq);
- X
- X/** handle left edge */
- X /* the corners are special cases */
- X if (row == 0)
- X fpoint[fpoints++] = p0; /* top */
- X else if (row == freq)
- X fpoint[fpoints++] = p1; /* bottom left */
- X else
- X {
- X /* This is the first side (point 0 to point 1) */
- X if (fcurrent.present & 1)
- X {
- X if (fcurrent.kind[0] == K_FACE)
- X {
- X /* these edge points belong to another face */
- X adj_face = fcurrent.index[0];
- X adj_edge = (fcurrent.edge & 3);
- X pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
- X fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
- X }
- X else if (fcurrent.kind[0] == K_QUAD)
- X {
- X /* these edge points belong to another face */
- X adj_quad = fcurrent.index[0];
- X adj_edge = (fcurrent.edge & 3);
- X pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
- X fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else sys_exit("fatal error 2"); /* should never occur! */
- X }
- X else
- X {
- X /* these edge points belong to THIS face; create point */
- X fpoint[fpoints++] = points;
- X finfo[f].edge_point[0][row-1] = points;
- X add_point(start.x, start.y, start.z);
- X }
- X }
- X
- X/** move across, left to right */
- X for (i = 0; i < row; i++)
- X {
- X add_the_point = 0;
- X
- X /* This point may be the bottom corner */
- X if (row == freq && i == row-1) fpoint[fpoints++] = p2;
- X
- X /* or it's the second side (point 1 to point 2) */
- X else if (row == freq && i != row-1)
- X {
- X if (fcurrent.present & 2) /* the edge exists */
- X {
- X if (fcurrent.kind[1] == K_FACE)
- X {
- X adj_face = fcurrent.index[1];
- X adj_edge = (fcurrent.edge >> 2) & 3;
- X pos = (fcurrent.direction & 2 ? freq-2-i : i);
- X fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
- X }
- X else if (fcurrent.kind[1] == K_QUAD)
- X {
- X adj_quad = fcurrent.index[1];
- X adj_edge = (fcurrent.edge >> 2) & 3;
- X pos = (fcurrent.direction & 2 ? freq-2-i : i);
- X fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else sys_exit("fatal error 3"); /* should never occur! */
- X }
- X else /* the edge must be created */
- X {
- X finfo[f].edge_point[1][i] = points;
- X add_the_point = 1;
- X }
- X }
- X
- X /* or it's the third side (point 2 to point 0) */
- X else if (row != freq && i == row-1)
- X {
- X if (fcurrent.present & 4) /* the edge exists */
- X {
- X if (fcurrent.kind[2] == K_FACE)
- X {
- X adj_face = fcurrent.index[2];
- X adj_edge = (fcurrent.edge >> 4) & 3;
- X /* the following is backwards: subtle note below */
- X pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
- X fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
- X }
- X else if (fcurrent.kind[2] == K_QUAD)
- X {
- X adj_quad = fcurrent.index[2];
- X adj_edge = (fcurrent.edge >> 4) & 3;
- X /* the following is backwards: subtle note below */
- X pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
- X fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
- X }
- X else sys_exit("fatal error 4"); /* should never occur! */
- X }
- X else /* the edge is created and specially numbered */
- X {
- X /* subtle point: we must be careful that the edge
- X vertices are entered in the same clockwisdom
- X as the vector point2->point0 */
- X finfo[f].edge_point[2][freq-row-1] = points;
- X add_the_point = 1;
- X }
- X }
- X /* otherwise, it's a point in the middle we need to create */
- X else add_the_point = 1;
- X
- X if (add_the_point)
- X {
- X fpoint[fpoints++] = points;
- X add_point(start.x + ((i+1) * vec[1].x / freq),
- X start.y + ((i+1) * vec[1].y / freq),
- X start.z + ((i+1) * vec[1].z / freq));
- X }
- X if (i > 0) add_face(fpoint[prev + i - 1],
- X fpoint[fpoints - 2],
- X fpoint[prev + i], colors.newface, 0);
- X add_face(fpoint[prev + i],
- X fpoint[fpoints - 2],
- X fpoint[fpoints - 1], colors.newface, 0);
- X }
- X }
- X }
- X
- X /* remove the old faces */
- X for (f = 0; f < old_faces; f++) delete_face(f, 0);
- X
- X /* remove the old polys */
- X for (q = 0; q < old_polys; q++)
- X if (poly[q].verts == 4) delete_poly(q, 0);
- X
- X /* free our temporary memory */
- X if (finfo) sys_free(finfo, sizeof(struct FaceInfo)*old_faces);
- X if (qinfo) sys_free(qinfo, sizeof(struct QuadInfo)*quads);
- X
- X convert_points();
- X return OKAY;
- X}
- X
- X
- END_OF_FILE
- if test 19873 -ne `wc -c <'freq.c'`; then
- echo shar: \"'freq.c'\" unpacked with wrong size!
- fi
- # end of 'freq.c'
- fi
- echo shar: End of archive 3 \(of 6\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-